//! S3存储适配器测试
//! 
//! 包含完整的单元测试、集成测试和性能测试

use super::*;
use tempfile::TempDir;
use tokio_test;

/// 测试S3存储适配器创建
#[tokio::test]
async fn test_s3_adapter_creation() {
    let config = S3StorageConfig::default();
    let adapter = S3StorageAdapter::new(config).await;
    assert!(adapter.is_ok(), "S3存储适配器创建应该成功");
}

/// 测试配置默认值
#[test]
fn test_default_config() {
    let config = S3StorageConfig::default();
    
    match config.storage_type {
        StorageType::Local { root_path } => {
            assert_eq!(root_path, "./data");
        }
        _ => panic!("默认配置应该是本地存储"),
    }
    
    assert_eq!(config.default_format, FileFormat::Auto);
    assert_eq!(config.enable_compression, true);
    assert_eq!(config.batch_size, 8192);
    assert_eq!(config.max_connections, 10);
    assert_eq!(config.connect_timeout, 30);
    assert_eq!(config.read_timeout, 300);
}

/// 测试文件格式检测
#[tokio::test]
async fn test_file_format_detection() {
    let config = S3StorageConfig::default();
    let adapter = S3StorageAdapter::new(config).await.unwrap();
    
    assert_eq!(adapter.detect_file_format("test.parquet"), FileFormat::Parquet);
    assert_eq!(adapter.detect_file_format("test.csv"), FileFormat::Csv);
    assert_eq!(adapter.detect_file_format("test.json"), FileFormat::Json);
    assert_eq!(adapter.detect_file_format("test.jsonl"), FileFormat::Json);
    assert_eq!(adapter.detect_file_format("test.txt"), FileFormat::Auto);
}

/// 测试表名提取
#[tokio::test]
async fn test_table_name_extraction() {
    let config = S3StorageConfig::default();
    let adapter = S3StorageAdapter::new(config).await.unwrap();
    
    assert_eq!(adapter.extract_table_name("data/users.parquet"), "users");
    assert_eq!(adapter.extract_table_name("orders.csv"), "orders");
    assert_eq!(adapter.extract_table_name("/path/to/products.json"), "products");
    assert_eq!(adapter.extract_table_name("unknown"), "unknown");
}

/// 测试存储统计信息
#[tokio::test]
async fn test_storage_stats() {
    let config = S3StorageConfig::default();
    let adapter = S3StorageAdapter::new(config).await.unwrap();
    
    let stats = adapter.get_stats().await;
    assert_eq!(stats.total_files, 0);
    assert_eq!(stats.total_size, 0);
    assert_eq!(stats.files_read, 0);
    assert_eq!(stats.bytes_read, 0);
    assert_eq!(stats.avg_read_time_ms, 0.0);
    assert!(stats.last_access_time.is_none());
}

/// 测试本地文件系统存储类型
#[tokio::test]
async fn test_local_storage_type() {
    let temp_dir = TempDir::new().unwrap();
    let root_path = temp_dir.path().to_string_lossy().to_string();
    
    let config = S3StorageConfig {
        storage_type: StorageType::Local { root_path: root_path.clone() },
        ..Default::default()
    };
    
    let adapter = S3StorageAdapter::new(config).await.unwrap();
    
    // 测试健康检查
    let health = adapter.health_check().await.unwrap();
    assert!(health, "本地存储健康检查应该通过");
}

/// 测试S3存储类型配置
#[test]
fn test_s3_storage_type() {
    let storage_type = StorageType::S3 {
        bucket: "test-bucket".to_string(),
        region: "us-east-1".to_string(),
        access_key_id: Some("test-key".to_string()),
        secret_access_key: Some("test-secret".to_string()),
    };
    
    match storage_type {
        StorageType::S3 { bucket, region, access_key_id, secret_access_key } => {
            assert_eq!(bucket, "test-bucket");
            assert_eq!(region, "us-east-1");
            assert_eq!(access_key_id, Some("test-key".to_string()));
            assert_eq!(secret_access_key, Some("test-secret".to_string()));
        }
        _ => panic!("应该是S3存储类型"),
    }
}

/// 测试Azure存储类型配置
#[test]
fn test_azure_storage_type() {
    let storage_type = StorageType::Azure {
        container: "test-container".to_string(),
        account: "test-account".to_string(),
        access_key: Some("test-key".to_string()),
    };
    
    match storage_type {
        StorageType::Azure { container, account, access_key } => {
            assert_eq!(container, "test-container");
            assert_eq!(account, "test-account");
            assert_eq!(access_key, Some("test-key".to_string()));
        }
        _ => panic!("应该是Azure存储类型"),
    }
}

/// 测试GCS存储类型配置
#[test]
fn test_gcs_storage_type() {
    let storage_type = StorageType::Gcs {
        bucket: "test-bucket".to_string(),
        service_account_key: Some("test-key".to_string()),
    };
    
    match storage_type {
        StorageType::Gcs { bucket, service_account_key } => {
            assert_eq!(bucket, "test-bucket");
            assert_eq!(service_account_key, Some("test-key".to_string()));
        }
        _ => panic!("应该是GCS存储类型"),
    }
}

/// 测试文件信息序列化
#[test]
fn test_file_info_serialization() {
    let file_info = FileInfo {
        path: "test/data.parquet".to_string(),
        size: 1024,
        format: FileFormat::Parquet,
        last_modified: chrono::Utc::now(),
        schema: None,
    };
    
    // 测试序列化
    let json = serde_json::to_string(&file_info).unwrap();
    assert!(json.contains("test/data.parquet"));
    assert!(json.contains("1024"));
    assert!(json.contains("Parquet"));
    
    // 测试反序列化
    let deserialized: FileInfo = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.path, file_info.path);
    assert_eq!(deserialized.size, file_info.size);
    assert_eq!(deserialized.format, file_info.format);
}

/// 测试存储统计信息序列化
#[test]
fn test_storage_stats_serialization() {
    let stats = StorageStats {
        total_files: 100,
        total_size: 1048576,
        files_read: 50,
        bytes_read: 524288,
        avg_read_time_ms: 15.5,
        last_access_time: Some(chrono::Utc::now()),
    };
    
    // 测试序列化
    let json = serde_json::to_string(&stats).unwrap();
    assert!(json.contains("100"));
    assert!(json.contains("1048576"));
    assert!(json.contains("15.5"));
    
    // 测试反序列化
    let deserialized: StorageStats = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.total_files, stats.total_files);
    assert_eq!(deserialized.total_size, stats.total_size);
    assert_eq!(deserialized.files_read, stats.files_read);
    assert_eq!(deserialized.bytes_read, stats.bytes_read);
    assert_eq!(deserialized.avg_read_time_ms, stats.avg_read_time_ms);
}

/// 测试配置序列化和反序列化
#[test]
fn test_config_serialization() {
    let config = S3StorageConfig {
        storage_type: StorageType::S3 {
            bucket: "test-bucket".to_string(),
            region: "us-west-2".to_string(),
            access_key_id: Some("test-key".to_string()),
            secret_access_key: Some("test-secret".to_string()),
        },
        default_format: FileFormat::Parquet,
        enable_compression: false,
        batch_size: 4096,
        max_connections: 20,
        connect_timeout: 60,
        read_timeout: 600,
    };
    
    // 测试序列化
    let json = serde_json::to_string(&config).unwrap();
    assert!(json.contains("test-bucket"));
    assert!(json.contains("us-west-2"));
    assert!(json.contains("Parquet"));
    
    // 测试反序列化
    let deserialized: S3StorageConfig = serde_json::from_str(&json).unwrap();
    match deserialized.storage_type {
        StorageType::S3 { bucket, region, .. } => {
            assert_eq!(bucket, "test-bucket");
            assert_eq!(region, "us-west-2");
        }
        _ => panic!("应该是S3存储类型"),
    }
    assert_eq!(deserialized.default_format, FileFormat::Parquet);
    assert_eq!(deserialized.enable_compression, false);
    assert_eq!(deserialized.batch_size, 4096);
}

/// 测试文件格式枚举
#[test]
fn test_file_format_enum() {
    // 测试相等性
    assert_eq!(FileFormat::Parquet, FileFormat::Parquet);
    assert_eq!(FileFormat::Csv, FileFormat::Csv);
    assert_eq!(FileFormat::Json, FileFormat::Json);
    assert_eq!(FileFormat::Auto, FileFormat::Auto);
    
    // 测试不相等性
    assert_ne!(FileFormat::Parquet, FileFormat::Csv);
    assert_ne!(FileFormat::Json, FileFormat::Auto);
    
    // 测试序列化
    let json = serde_json::to_string(&FileFormat::Parquet).unwrap();
    assert_eq!(json, "\"Parquet\"");
    
    let json = serde_json::to_string(&FileFormat::Auto).unwrap();
    assert_eq!(json, "\"Auto\"");
}

/// 性能测试：文件格式检测
#[test]
fn test_file_format_detection_performance() {
    let start = std::time::Instant::now();
    
    // 模拟大量文件格式检测
    for i in 0..10000 {
        let path = format!("file_{}.parquet", i);
        let format = if path.ends_with(".parquet") {
            FileFormat::Parquet
        } else if path.ends_with(".csv") {
            FileFormat::Csv
        } else if path.ends_with(".json") {
            FileFormat::Json
        } else {
            FileFormat::Auto
        };
        assert_eq!(format, FileFormat::Parquet);
    }
    
    let duration = start.elapsed();
    assert!(duration.as_millis() < 100, "文件格式检测性能测试失败，耗时: {:?}", duration);
}

/// 边界条件测试
#[tokio::test]
async fn test_edge_cases() {
    let config = S3StorageConfig::default();
    let adapter = S3StorageAdapter::new(config).await.unwrap();
    
    // 测试空路径
    assert_eq!(adapter.extract_table_name(""), "unknown");
    
    // 测试只有扩展名的文件
    assert_eq!(adapter.extract_table_name(".parquet"), "");
    
    // 测试没有扩展名的文件
    assert_eq!(adapter.detect_file_format("filename"), FileFormat::Auto);
    
    // 测试多个点的文件名
    assert_eq!(adapter.extract_table_name("file.backup.parquet"), "file.backup");
}

/// 并发测试
#[tokio::test]
async fn test_concurrent_access() {
    let config = S3StorageConfig::default();
    let adapter = Arc::new(S3StorageAdapter::new(config).await.unwrap());
    
    // 创建多个并发任务
    let mut handles = vec![];
    for i in 0..10 {
        let adapter_clone = adapter.clone();
        let handle = tokio::spawn(async move {
            let stats = adapter_clone.get_stats().await;
            assert_eq!(stats.total_files, 0);
            i
        });
        handles.push(handle);
    }
    
    // 等待所有任务完成
    for handle in handles {
        let result = handle.await.unwrap();
        assert!(result < 10);
    }
}

/// 测试错误处理
#[tokio::test]
async fn test_error_handling() {
    // 测试无效的本地路径
    let config = S3StorageConfig {
        storage_type: StorageType::Local {
            root_path: "/invalid/path/that/does/not/exist".to_string(),
        },
        ..Default::default()
    };
    
    let result = S3StorageAdapter::new(config).await;
    // 这可能成功也可能失败，取决于object_store的实现
    match result {
        Ok(adapter) => {
            // 如果创建成功，健康检查应该失败
            let health = adapter.health_check().await.unwrap();
            // 可能返回false或者抛出错误
        }
        Err(_) => {
            // 预期的错误
        }
    }
}

/// 集成测试：完整的存储流程
#[tokio::test]
async fn test_storage_integration() {
    let temp_dir = TempDir::new().unwrap();
    let root_path = temp_dir.path().to_string_lossy().to_string();
    
    let config = S3StorageConfig {
        storage_type: StorageType::Local { root_path },
        ..Default::default()
    };
    
    let adapter = S3StorageAdapter::new(config).await.unwrap();
    
    // 测试健康检查
    let health = adapter.health_check().await.unwrap();
    assert!(health, "健康检查应该通过");
    
    // 测试文件列表（空目录）
    let files = adapter.list_files(None).await.unwrap();
    assert_eq!(files.len(), 0, "空目录应该没有文件");
    
    // 测试统计信息
    let stats = adapter.get_stats().await;
    assert_eq!(stats.total_files, 0);
    assert_eq!(stats.total_size, 0);
}
